home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 176-200 / 190 / nethack / twee.zoo / lev.c < prev    next >
C/C++ Source or Header  |  1988-08-04  |  14KB  |  639 lines

  1. /*    SCCS Id: @(#)lev.c      2.3     88/01/24
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. #include <stdio.h>
  5. #include "hack.h"
  6. #include "mkroom.h"
  7. extern struct monst *restmonchn();
  8. extern struct obj *restobjchn();
  9. extern struct obj *billobjs;
  10. extern char *itoa();
  11. extern char SAVEF[];
  12. extern int hackpid;
  13. extern xchar dlevel;
  14. extern char nul[];
  15.  
  16. #ifndef NOWORM
  17. #include    "wseg.h"
  18. extern struct wseg *wsegs[32], *wheads[32];
  19. extern long wgrowtime[32];
  20. #endif
  21.  
  22. #ifdef DGK
  23. struct finfo fileinfo[MAXLEVEL+1];
  24. long bytes_counted;
  25. int count_only;
  26. #else
  27. boolean level_exists[MAXLEVEL+1];
  28. #endif
  29.  
  30. #ifdef DGK
  31. savelev(fd, lev, mode)
  32. int fd, mode;
  33. xchar lev;
  34. {
  35.     if (mode & COUNT) {
  36. #ifdef COMPRESS /* Should be superfluous */
  37.         if (!count_only)    /* Did we just write? */
  38.             bflush(0);
  39.         /*dbg();*/
  40. #endif
  41.         count_only = TRUE;
  42.         bytes_counted = 0;
  43.         savelev0(fd, lev);
  44.         while (bytes_counted > freediskspace(levels))
  45.             if (!swapout_oldest())
  46.                 return FALSE;
  47.     }
  48.     if (mode & WRITE) {
  49. #ifdef COMPRESS
  50.         if (mode & COUNT)    /* Did we just count? */
  51.             bflush(fd);
  52. #endif
  53.         count_only = FALSE;
  54.         bytes_counted = 0;
  55.         savelev0(fd, lev);
  56.     }
  57.     fileinfo[lev].where = ACTIVE;
  58.     fileinfo[lev].time = moves;
  59.     fileinfo[lev].size = bytes_counted;
  60.     return TRUE;
  61. }
  62.  
  63. savelev0(fd,lev)
  64. #else
  65. savelev(fd,lev)
  66. #endif
  67. int fd;
  68. xchar lev;
  69. {
  70. #ifndef NOWORM
  71.     register struct wseg *wtmp, *wtmp2;
  72.     register tmp;
  73. #endif
  74.  
  75.     if(fd < 0) panic("Save on bad file!");  /* impossible */
  76. #ifndef DGK
  77.     if(lev >= 0 && lev <= MAXLEVEL)
  78.         level_exists[lev] = TRUE;
  79. #endif
  80.     bwrite(fd,(char *) &hackpid,sizeof(hackpid));
  81.     bwrite(fd,(char *) &lev,sizeof(lev));
  82.     bwrite(fd,(char *) levl,sizeof(levl));
  83. #ifdef GRAPHICS
  84.     bwrite(fd, (char *) &showsyms, sizeof(struct symbols));
  85. #endif
  86.     bwrite(fd,(char *) &moves,sizeof(long));
  87.     bwrite(fd,(char *) &xupstair,sizeof(xupstair));
  88.     bwrite(fd,(char *) &yupstair,sizeof(yupstair));
  89.     bwrite(fd,(char *) &xdnstair,sizeof(xdnstair));
  90.     bwrite(fd,(char *) &ydnstair,sizeof(ydnstair));
  91.     savemonchn(fd, fmon);
  92.     savegoldchn(fd, fgold);
  93.     savetrapchn(fd, ftrap);
  94.     saveobjchn(fd, fobj);
  95.     saveobjchn(fd, billobjs);
  96.     save_engravings(fd);
  97. #ifndef QUEST
  98.     bwrite(fd,(char *) rooms,sizeof(rooms));
  99.     bwrite(fd,(char *) doors,sizeof(doors));
  100. #endif
  101. #ifndef NOWORM
  102.     bwrite(fd,(char *) wsegs,sizeof(wsegs));
  103.     for(tmp=1; tmp<32; tmp++){
  104.         for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){
  105.             wtmp2 = wtmp->nseg;
  106.             bwrite(fd,(char *) wtmp,sizeof(struct wseg));
  107.         }
  108. #ifdef DGK
  109.         if (!count_only)
  110. #endif
  111.             wsegs[tmp] = 0;
  112.     }
  113.     bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime));
  114. #endif /* NOWORM /**/
  115. #ifdef DGK
  116.     if (count_only) return(0);
  117. #endif
  118.     billobjs = 0;
  119.     fgold = 0;
  120.     ftrap = 0;
  121.     fmon = 0;
  122.     fobj = 0;
  123. }
  124.  
  125. #ifdef COMPRESS
  126.  
  127. #define RLESC    '\0'    /* Leading character for run of LRESC's */
  128. #define flushoutrun(ln) bputc(RLESC); bputc(ln); ln = -1;
  129.  
  130. static unsigned char outbuf[BUFSZ];
  131. static unsigned short outbufp = 0;
  132. static short outrunlength = -1;
  133. static int bwritefd;
  134.  
  135. /*dbg()
  136. {
  137.    printf("outbufp %d outrunlength %d\n", outbufp,outrunlength);
  138. }*/
  139.  
  140. static bputc(c)
  141. unsigned char c;
  142. {
  143. #ifdef    DGK
  144.     bytes_counted++;
  145.     if (count_only)
  146.     return;
  147. #endif
  148.     if (outbufp >= BUFSZ) {
  149.     write(bwritefd, outbuf, (int) BUFSZ);
  150.     outbufp = 0;
  151.     }
  152.     outbuf[outbufp++] = c;
  153. }
  154.  
  155. bflush(fd)  /* flush run and buffer */
  156. register fd;
  157. {
  158.     bwritefd = fd;
  159.     if (outrunlength >= 0) {    /* flush run */
  160.         flushoutrun(outrunlength);
  161.     }
  162.     if (outbufp) {
  163. #ifdef    DGK
  164.         if (!count_only)    /* flush buffer */
  165. #endif
  166.             write(fd, outbuf, outbufp);
  167.         outbufp = 0;
  168.     }
  169.     /*printf("bflush()"); getret();*/
  170. }
  171.  
  172. bwrite(fd, loc, num)
  173. register fd;
  174. register char *loc;
  175. register unsigned num;
  176. {
  177.     bwritefd = fd;
  178.     for (; num; num--, loc++) {
  179.         if (*loc == RLESC) { /* One more char in run */
  180.             if (++outrunlength == 0xFF) {
  181.             flushoutrun(outrunlength);
  182.             }
  183.         } else { /* end of run */
  184.             if (outrunlength >= 0) {    /* flush run */
  185.             flushoutrun(outrunlength);
  186.             }
  187.             bputc(*loc);
  188.         }
  189.     }
  190. }
  191.  
  192. static unsigned char inbuf[BUFSZ];
  193. static unsigned short inbufp = 0;
  194. static unsigned short inbufsz = 0;
  195. static short inrunlength = -1;
  196. static int mreadfd;
  197.  
  198. static int mgetc()
  199. {
  200.     if (inbufp >= inbufsz) {
  201.     inbufsz = read(mreadfd, (char *)inbuf, (int)sizeof inbuf);
  202.     if (!inbufsz) {
  203.         if (inbufp > sizeof inbuf)
  204.         error("EOF on file #%d.\n", mreadfd);
  205.         inbufp = 1 + sizeof inbuf;    /* exactly one warning :-) */
  206.         return -1;
  207.     }
  208.     inbufp = 0;
  209.     }
  210.     return inbuf[inbufp++];
  211. }
  212.  
  213. minit()
  214. {
  215.     inbufsz = 0;
  216.     inbufp = 0;
  217.     inrunlength = -1;
  218. }
  219.  
  220. mread(fd, buf, len)
  221. int fd;
  222. register char *buf;
  223. register unsigned len;
  224. {
  225.     /*register int readlen = 0;*/
  226.     mreadfd = fd;
  227.     while (len--) {
  228.     if (inrunlength > 0) {
  229.         inrunlength--;
  230.         *buf++ = '\0';
  231.     } else {
  232.         register short ch = mgetc();
  233.         if (ch < 0) return -1; /*readlen;*/
  234.         if ((*buf++ = ch) == RLESC) {
  235.         inrunlength = mgetc();
  236.         }
  237.     }
  238.     /*readlen++;*/
  239.     }
  240.     return 0; /*readlen;*/
  241. }
  242.  
  243. #else /* COMPRESS */
  244.  
  245. bwrite(fd,loc,num)
  246. register fd;
  247. register char *loc;
  248. register unsigned num;
  249. {
  250. #ifdef DGK
  251.     bytes_counted += num;
  252.     if (!count_only)
  253. #endif
  254. /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
  255.         if(write(fd, loc, (int) num) != num)
  256.         panic("cannot write %u bytes to file #%d", num, fd);
  257. }
  258.  
  259. mread(fd, buf, len)
  260. register fd;
  261. register char *buf;
  262. register unsigned len;
  263. {
  264.     register int rlen;
  265.     extern boolean restoring;
  266.  
  267.     rlen = read(fd, buf, (int) len);
  268.     if(rlen != len){
  269.         pline("Read %d instead of %u bytes.\n", rlen, len);
  270.         if(restoring) {
  271.             (void) unlink(SAVEF);
  272.             error("Error restoring old game.");
  273.         }
  274.         panic("Error reading level file.");
  275.     }
  276. }
  277. #endif
  278.  
  279. saveobjchn(fd,otmp)
  280. register fd;
  281. register struct obj *otmp;
  282. {
  283.     register struct obj *otmp2;
  284.     unsigned xl;
  285.     int minusone = -1;
  286.  
  287.     while(otmp) {
  288.         otmp2 = otmp->nobj;
  289.         xl = otmp->onamelth;
  290.         bwrite(fd, (char *) &xl, sizeof(int));
  291.         bwrite(fd, (char *) otmp, xl + sizeof(struct obj));
  292. #ifdef DGK
  293.         if (!count_only)
  294. #endif
  295.             free((char *) otmp);
  296.         otmp = otmp2;
  297.     }
  298.     bwrite(fd, (char *) &minusone, sizeof(int));
  299. }
  300.  
  301. savemonchn(fd,mtmp)
  302. register fd;
  303. register struct monst *mtmp;
  304. {
  305.     register struct monst *mtmp2;
  306.     unsigned xl;
  307.     int minusone = -1;
  308.     struct permonst *monbegin = &mons[0];
  309.  
  310.     bwrite(fd, (char *) &monbegin, sizeof(monbegin));
  311.  
  312.     while(mtmp) {
  313.         mtmp2 = mtmp->nmon;
  314.         xl = mtmp->mxlth + mtmp->mnamelth;
  315.         bwrite(fd, (char *) &xl, sizeof(int));
  316.         bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
  317.         if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
  318. #ifdef DGK
  319.         if (!count_only)
  320. #endif
  321.             free((char *) mtmp);
  322.         mtmp = mtmp2;
  323.     }
  324.     bwrite(fd, (char *) &minusone, sizeof(int));
  325. }
  326.  
  327. savegoldchn(fd,gold)
  328. register fd;
  329. register struct gold *gold;
  330. {
  331.     register struct gold *gold2;
  332.     while(gold) {
  333.         gold2 = gold->ngold;
  334.         bwrite(fd, (char *) gold, sizeof(struct gold));
  335. #ifdef DGK
  336.         if (!count_only)
  337. #endif
  338.             free((char *) gold);
  339.         gold = gold2;
  340.     }
  341.     bwrite(fd, nul, sizeof(struct gold));
  342. }
  343.  
  344. savetrapchn(fd,trap)
  345. register fd;
  346. register struct trap *trap;
  347. {
  348.     register struct trap *trap2;
  349.     while(trap) {
  350.         trap2 = trap->ntrap;
  351.         bwrite(fd, (char *) trap, sizeof(struct trap));
  352. #ifdef DGK
  353.         if (!count_only)
  354. #endif
  355.             free((char *) trap);
  356.         trap = trap2;
  357.     }
  358.     bwrite(fd, nul, sizeof(struct trap));
  359. }
  360.  
  361. getlev(fd,pid,lev)
  362. int fd,pid;
  363. xchar lev;
  364. {
  365.     register struct gold *gold;
  366.     register struct trap *trap;
  367. #ifndef NOWORM
  368.     register struct wseg *wtmp;
  369. #endif
  370.     register tmp;
  371.     long omoves;
  372.     int hpid;
  373.     xchar dlvl;
  374. #ifdef GRAPHICS
  375.     struct symbols osymbol;
  376.     int x, y, up, dn, lt, rt;
  377.     uchar osym, nsym;
  378. #endif
  379.  
  380. #ifdef MSDOS
  381.     setmode(fd,O_BINARY);
  382. #endif
  383.     /* First some sanity checks */
  384.     mread(fd, (char *) &hpid, sizeof(hpid));
  385.     mread(fd, (char *) &dlvl, sizeof(dlvl));
  386.     if((pid && pid != hpid) || (lev && dlvl != lev)) {
  387.         pline("Strange, this map is not as I remember it.");
  388.          /* pline("pid = %x (%x), lev = %d (%d).", hpid, pid, dlvl, lev); */
  389.         pline("Somebody is trying some trickery here ...");
  390.         pline("This game is void ...");
  391.         done("tricked");
  392.     }
  393.  
  394.     mread(fd, (char *) levl, sizeof(levl));
  395. #ifdef GRAPHICS
  396.     /* Corners are poorly implemented.  They only exist in the
  397.      * scrsym field of each dungeon element.  So we have to go
  398.      * through the previous level, looking for scrsym with the
  399.      * old corner values, checking to make sure that they are
  400.      * where corners should be, then replace them with the scrsym
  401.      * of the new GRAPHICS character set.  Ugly.
  402.      */
  403.     mread(fd, (char *) &osymbol, sizeof(osymbol));
  404.     if (memcmp((char *) &osymbol, (char *) &showsyms, sizeof (struct symbols))) {
  405.         for (x = 0; x < COLNO; x++)
  406.             for (y = 0; y < ROWNO; y++) {
  407.                 osym = levl[x][y].scrsym;
  408.                 nsym = 0;
  409.                 switch (RM_TYP(levl[x][y])) {
  410.                 case 0:
  411.                 case SCORR:
  412.                     break;
  413.                 case ROOM:
  414.                     if (osym == osymbol.room)
  415.                         nsym = showsyms.room;
  416.                     break;
  417.                 case DOOR:
  418.                     if (osym == osymbol.door)
  419.                         nsym = showsyms.door;
  420.                     break;
  421.                 case CORR:
  422.                     if (osym == osymbol.corr)
  423.                         nsym = showsyms.corr;
  424.                     break;
  425.                 case VWALL:
  426.                     if (osym == osymbol.vwall)
  427.                         nsym = showsyms.vwall;
  428.                     break;
  429.                 case SDOOR:
  430.                     if (osym == osymbol.vwall)
  431.                         nsym = showsyms.vwall;
  432.                     else if (osym == osymbol.hwall)
  433.                         nsym = showsyms.hwall;
  434.                     break;
  435.                 /* Now the ugly stuff */
  436.                 case HWALL:
  437.                   up = (y > 0) ? RM_TYP(levl[x][y-1]) : 0;
  438.                   dn = (y < ROWNO-1) ? RM_TYP(levl[x][y+1]) : 0;
  439.                   lt = (x > 0) ? RM_TYP(levl[x-1][y]) : 0;
  440.                   rt = (x < COLNO-1) ? RM_TYP(levl[x+1][y]) : 0;
  441.                   up = up && (up == VWALL || up == DOOR
  442.                     || up == SDOOR);
  443.                   dn = dn && (dn == VWALL || dn == DOOR
  444.                     || dn == SDOOR);
  445.                   lt = lt && (lt == HWALL || lt == DOOR
  446.                     || lt == SDOOR);
  447.                   rt = rt && (rt == HWALL || rt == DOOR
  448.                     || rt == SDOOR);
  449.                   if (rt && dn && osym == osymbol.tlcorn)
  450.                     nsym = showsyms.tlcorn;
  451.                   else if (lt && dn && osym == osymbol.trcorn)
  452.                     nsym = showsyms.trcorn;
  453.                   else if (rt && up && osym == osymbol.blcorn)
  454.                     nsym = showsyms.blcorn;
  455.                   else if (lt && up && osym == osymbol.brcorn)
  456.                     nsym = showsyms.brcorn;
  457.                   else if (osym == osymbol.hwall)
  458.                     nsym = showsyms.hwall;
  459.                   break;
  460.                 default:
  461.                     break;
  462.                 }
  463.                 if (nsym)
  464.                     levl[x][y].scrsym = nsym;
  465.             }
  466.     }
  467. #endif
  468.     mread(fd, (char *)&omoves, sizeof(omoves));
  469.     mread(fd, (char *)&xupstair, sizeof(xupstair));
  470.     mread(fd, (char *)&yupstair, sizeof(yupstair));
  471.     mread(fd, (char *)&xdnstair, sizeof(xdnstair));
  472.     mread(fd, (char *)&ydnstair, sizeof(ydnstair));
  473.  
  474.     fmon = restmonchn(fd);
  475.  
  476.     /* regenerate animals while on another level */
  477.     { long tmoves = (moves > omoves) ? moves-omoves : 0;
  478.       register struct monst *mtmp, *mtmp2;
  479.       extern char genocided[];
  480.  
  481.       for(mtmp = fmon; mtmp; mtmp = mtmp2) {
  482.         long newhp;        /* tmoves may be very large */
  483.  
  484.         mtmp2 = mtmp->nmon;
  485.         if(index(genocided, mtmp->data->mlet)) {
  486.             mondead(mtmp);
  487.             continue;
  488.         }
  489.  
  490.         if(mtmp->mtame && tmoves > 250) {
  491.             mtmp->mtame = 0;
  492.             mtmp->mpeaceful = 0;
  493.         }
  494.  
  495.         /* restore shape changers - Maarten Jan Huisjes */
  496.         if (mtmp->data->mlet == ':' && !Protection_from_shape_changers
  497.             && !mtmp->cham)
  498.             mtmp->cham = 1;
  499.         else if(mtmp->cham && Protection_from_shape_changers) {
  500.             mtmp->cham = 0;
  501.             (void) newcham(mtmp, PM_CHAMELEON);
  502.         }
  503.  
  504.         newhp = mtmp->mhp +
  505.             (index(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20);
  506.         if(newhp > mtmp->mhpmax)
  507.             mtmp->mhp = mtmp->mhpmax;
  508.         else
  509.             mtmp->mhp = newhp;
  510.       }
  511.     }
  512.  
  513.     setgd();
  514.     fgold = 0;
  515.     while(gold = newgold(),
  516.           mread(fd, (char *)gold, sizeof(struct gold)),
  517.           gold->gx) {
  518.         gold->ngold = fgold;
  519.         fgold = gold;
  520.     }
  521.     free((char *) gold);
  522.     ftrap = 0;
  523.     while (trap = newtrap(),
  524.            mread(fd, (char *)trap, sizeof(struct trap)),
  525.            trap->tx) {
  526.         trap->ntrap = ftrap;
  527.         ftrap = trap;
  528.     }
  529.     free((char *) trap);
  530.     fobj = restobjchn(fd);
  531.     billobjs = restobjchn(fd);
  532.     rest_engravings(fd);
  533. #ifndef QUEST
  534.     mread(fd, (char *)rooms, sizeof(rooms));
  535.     mread(fd, (char *)doors, sizeof(doors));
  536. #endif
  537. #ifndef NOWORM
  538.     mread(fd, (char *)wsegs, sizeof(wsegs));
  539.     for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){
  540.         wheads[tmp] = wsegs[tmp] = wtmp = newseg();
  541.         while(1) {
  542.             mread(fd, (char *)wtmp, sizeof(struct wseg));
  543.             if(!wtmp->nseg) break;
  544.             wheads[tmp]->nseg = wtmp = newseg();
  545.             wheads[tmp] = wtmp;
  546.         }
  547.     }
  548.     mread(fd, (char *)wgrowtime, sizeof(wgrowtime));
  549. #endif
  550. }
  551.  
  552.  
  553. mklev()
  554. {
  555.     extern boolean in_mklev;
  556.  
  557.     if(getbones()) return;
  558.  
  559.     in_mklev = TRUE;
  560.     makelevel();
  561.     in_mklev = FALSE;
  562. }
  563.  
  564. #ifdef DGK
  565. swapin_file(lev) {
  566.     char to[PATHLEN], from[PATHLEN];
  567.  
  568.     sprintf(from, "%s%s", permbones, alllevels);
  569.     sprintf(to, "%s%s", levels, alllevels);
  570.     name_file(from, lev);
  571.     name_file(to, lev);
  572.     while (fileinfo[lev].size > freediskspace(to))
  573.         if (!swapout_oldest())
  574.             return FALSE;
  575. #ifdef WIZARD
  576.     if (wizard) {
  577.         pline("Swapping in `%s'", from);
  578.         fflush(stdout);
  579.     }
  580. #endif
  581.     copyfile(from, to);
  582.     (void) unlink(from);
  583.     fileinfo[lev].where = ACTIVE;
  584.     return TRUE;
  585. }
  586.  
  587.  
  588. swapout_oldest() {
  589.     char to[PATHLEN], from[PATHLEN];
  590.     int i, oldest;
  591.     long oldtime;
  592.  
  593.     if (!ramdisk)
  594.         return FALSE;
  595.     for (i = 1, oldtime = 0, oldest = 0; i <= maxdlevel; i++)
  596.         if (fileinfo[i].where == ACTIVE
  597.         && (!oldtime || fileinfo[i].time < oldtime)) {
  598.             oldest = i;
  599.             oldtime = fileinfo[i].time;
  600.         }
  601.     if (!oldest)
  602.         return FALSE;
  603.     sprintf(from, "%s%s", levels, alllevels);
  604.     sprintf(to, "%s%s", permbones, alllevels);
  605.     name_file(from, oldest);
  606.     name_file(to, oldest);
  607. #ifdef WIZARD
  608.     if (wizard) {
  609.         pline("Swapping out `%s'.", from);
  610.         fflush(stdout);
  611.     }
  612. #endif
  613.     copyfile(from, to);
  614.     unlink(from);
  615.     fileinfo[oldest].where = SWAPPED;
  616.     return TRUE;
  617. }
  618.  
  619. copyfile(from, to)
  620. char *from, *to;
  621. {
  622.     char buf[BUFSIZ];
  623.     int nfrom, nto, fdfrom, fdto;
  624.  
  625.     if ((fdfrom = open(from, O_RDONLY | O_BINARY, FMASK)) < 0)
  626.         panic("Can't copy from %s !?", from);
  627.     if ((fdto = open(to, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, FMASK)) < 0)
  628.         panic("Can't copy to %s", to);
  629.     do {
  630.         nfrom = read(fdfrom, buf, BUFSIZ);
  631.         nto = write(fdto, buf, nfrom);
  632.         if (nto != nfrom)
  633.             panic("Copyfile failed!");
  634.     } while (nfrom == BUFSIZ);
  635.     close(fdfrom);
  636.     close(fdto);
  637. }
  638. #endif
  639.